﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

// Wrap all the calls to zip/gzip functionality provided by libzip, so that we can remove it and its liscense

#if LIBZIP
using WowAceUpdater.libzip.GZip;
using WowAceUpdater.libzip.Zip;
using System.Reflection;
#else
using System.IO.Compression;
using WowAceUpdater.mszip;
#endif

namespace WowAceUpdater
{
    static class Compression
    {

        static internal Stream OpenGZipInputStream(Stream fs)
        {
#if LIBZIP
            return new GZipInputStream(fs);
#else
            return new GZipStream(fs, CompressionMode.Decompress);
#endif
        }

        static internal Stream OpenGZipOutputStream(Stream fs)
        {
#if LIBZIP
            return new GZipOutputStream(fs);
#else
            return new GZipStream(fs, CompressionMode.Compress);
#endif
        }

        static internal List<string> GetZipContentsList(string addonName, string localZipPath)
        {
            List<string> zipfiles = new List<string>();
#if LIBZIP
            try
            {
                using (ZipFile z = new ZipFile(localZipPath))
                {
                    Program.LogDbg(string.Format("{0} Reading new zip {1} entries",
                                                 addonName, z.Count));
                    foreach (ZipEntry f in z)
                        zipfiles.Add(f.Name);
                }
            }
            catch (Exception e)
            {
                Program.LogDbg(e.ToString());
            }
            
#else
            try
            {
                ZipFile z = new ZipFile(localZipPath);
                Program.LogDbg(string.Format("{0} Reading new zip {1} entries",
                                             addonName, z.Entries.Count));
                foreach (ZipEntry f in z.Entries)
                    zipfiles.Add(f.Name);
            }
            catch (Exception e)
            {
                Program.LogDbg(e.ToString());
            }
#endif

            return zipfiles;
        }

        static internal void ExtractZipFile(string zipFilePath, string destinationFolder)
        {
#if LIBZIP
            try
            {
                FastZip zip = new FastZip();
                zip.CreateEmptyDirectories = true;
                zip.ExtractZip(zipFilePath, destinationFolder, "");
            }
            catch
            {
                // ZipLib has a known error where it fails on files in the zip that are zero length, so
                // if #ziplib fails, drop back to Shell32 unzipping
                // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/objects/folder/copyhere.asp
                //
                // I'm using late binding instead of the following code because I think there is a bug
                // with the interface IDs that are used on Vista and this seems to fix it.
                // 
                // This is the strong typed form
                // ShellClass shell = new ShellClass();
                // Folder src = shell.NameSpace(zipFilePath);
                // Folder dest = shell.NameSpace(destinationFolder);
                // dest.CopyHere(src.Items(), CopyHereOptions.NoProgressDlg);

                Type shellType = Type.GetTypeFromProgID("Shell.Application");
                object shellObject = Activator.CreateInstance(shellType);

                object src =
                    shellType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shellObject,
                                           new object[] {zipFilePath});
                object dest =
                    shellType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shellObject,
                                           new object[] {destinationFolder});

                Type folderType = Type.GetTypeFromCLSID(new Guid("BBCBDE60-C3FF-11CE-8350-444553540000"));
 //               Type folderItemsType = Type.GetTypeFromCLSID(new Guid("744129E0-CBE5-11CE-8350-444553540000"));

                object items = folderType.InvokeMember("Items", BindingFlags.InvokeMethod, null, src, new object[] {});

                folderType.InvokeMember("CopyHere", BindingFlags.InvokeMethod, null, dest,
                                        new object[] {items, WowAceUpdater.FileSystem.CopyHereOptions.NoProgressDlg});
            }

#else
            ZipFile z = new ZipFile(zipFilePath);

            z.ExtractAll(destinationFolder);
#endif
        }
    }
}
